#include "Scene.h"
#include "TextureMgr.h"
#include "CelBackground.h"

/*
 *  The global Orbiter scene. There is only scene in the entire
 *  client. Its created in D3D11Client.
 */
Scene *gScene;

Scene::Scene(D3D11Client *pGC) {

	mGraphicsClient = pGC;
	Proxy_new = Proxy = NULL;
}

Scene::~Scene() {
    DeleteGlobalVars();

    delete pSketch;
    delete mCelBkgrnd;

    REL( PBuffer_Surf );
    REL( PBuffer_RTV );
    REL( PBuffer_SRV );
    REL( PBuffer );
    REL( BackBuffer_RTV );
    REL( BackBuffer );
    REL( RTarget_DSV );
}

//=================================================
//            Update.
//=================================================

bool Scene::IsVisibleInCamera( D3DXVECTOR3 *pCnt, float radius ) {
//tilemanger, cloudmanager:
    float z = camera_z.x*pCnt->x + camera_z.y*pCnt->y + camera_z.z*pCnt->z;
    if( z < (-radius) ) return false;
    if( z < 0) z=-z;
    float y = camera_y.x*pCnt->x + camera_y.y*pCnt->y + camera_y.z*pCnt->z;
    if( y < 0) y=-y;
    if( y - (radius*vhf) > (vh*z) ) return false;
    float x = camera_x.x*pCnt->x + camera_x.y*pCnt->y + camera_x.z*pCnt->z;
    if( x < 0 ) x=-x;
    if( x - (radius*vwf) > (vw*z) ) return false;
    return true;
}

void Scene::SaveParams() {
    DWORD j;
    MATRIX3 Rot;

    GetTextureMgr()->FrameRendered();
    D3D11Config *config = mGraphicsClient->getConfig();
    
    //set view matrix
    CamAperture_new = oapiCameraAperture();
    config->Aspect = Aspect = (float)config->cWidth/(float)config->cHeight;
    oapiCameraRotationMatrix( &Rot );
    M3ToDM( &View_new, &Rot );

    //find proxy planet/sun
    oapiCameraGlobalPos( &CamPos_new );
    Proxy_new = oapiCameraProxyGbody();

    mCelBkgrnd->SaveParams( 8, BgLvl );

    //current planetarium mode config
    PlanetariumFlag = *(DWORD*)mGraphicsClient->GetConfigParam( CFGPRM_PLANETARIUMFLAG );

    //get debug string
    char *line = oapiDebugString();
    if( line ) {
        strcpy( debug_str, line );
        debug_len = strlen( debug_str );
    }
    else
        debug_len = 0;

    //virtual cockpit projection matrix
    D3DXMatrixPerspectiveFovLH( &Proj_new, (float)(CamAperture_new*2.0), config->Aspect, 0.15f, 1e6 );
    ViewProj_VC_new = View_new*Proj_new;

    //external projection matrix
    D3DXMatrixPerspectiveFovLH( &Proj_new, (float)(CamAperture_new*2.0), config->Aspect, near_plane, far_plane );
    ViewProj_new = View_new*Proj_new;
}

void Scene::Update() {
    DWORD j;

	D3D11Config* config = mGraphicsClient->getConfig();

    View = View_new;
    Proj = Proj_new;
    ViewProj = ViewProj_new;            //VP matrix for exterior views
    ViewProj_VC = ViewProj_VC_new;        //VP matrix for VC
    CamPos = CamPos_new;
    CamAperture = CamAperture_new;

    vh   = (float)tan(CamAperture);
    vw   = vh*config->Aspect;
    vhf  = (float)(1.0f/cos(CamAperture));
    vwf  = vhf*config->Aspect;

    camera_x = D3DXVECTOR3(View._11, View._21, View._31);
    camera_y = D3DXVECTOR3(View._12, View._22, View._32);
    camera_z = D3DXVECTOR3(View._13, View._23, View._33);

    Proxy = Proxy_new;
}

bool Scene::IsVisiblePoint( D3DXVECTOR3 *vec ) {
    return (D3DXVec3Dot( vec, &camera_z ) > 0.0f ? false : true);
}

TextureMgr*
Scene::GetTextureMgr()
{
    return mGraphicsClient->getTextureMgr();
}

//=================================================
//            Rendering.
//=================================================

void Scene::Render_0() {
    DWORD j;

    int distcomp( const void *arg1, const void *arg2 );    //compares object by their distance from camera

//    APRM = NULL;
    //pSketch = new D3D11Pad( NULL, GetTextureMgr() );
    D3DXCOLOR ClearColor( cBackground.x, cBackground.y, cBackground.z, 0.0f );
    
     iCtx->ClearRenderTargetView( RTarget_RTV, ClearColor );
    
    iCtx->ClearDepthStencilView( RTarget_DSV, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0 );
    SetRenderTarget();

//    iCtx->ClearRenderTargetView( RTarget_RTV, ClearColor );
    iCtx->OMSetDepthStencilState( DSS_NoDepth_NoStencil, 0 );

	D3D11Config* config = mGraphicsClient->getConfig();

    D3D11_VIEWPORT VP;
    VP.Width = (FLOAT)config->cWidth;
    VP.Height = (FLOAT)config->cHeight;
    VP.MinDepth = 0.0f;
    VP.MaxDepth = 1.0f;
    VP.TopLeftX = 0;
    VP.TopLeftY = 0;
    iCtx->RSSetViewports( 1, &VP );

    //================================================
    //                        Stars
    //================================================
    //background
    mCelBkgrnd->Render();


}

void Scene::Render_1() {

    //==========================================================================================================
    //        Vessels: Shadows -> Meshes -> Beacons -> Exhaust -> Particle Streams -> Markers
    //==========================================================================================================

}

void Scene::SetRenderTarget()
{
    iCtx->OMSetRenderTargets( 1, &RTarget_RTV, RTarget_DSV );
}

//===========================================================
//                    INIT
//===========================================================
#pragma region init
void Scene::Init3D() 
{
	D3D11Config* config = mGraphicsClient->getConfig();

    //create swap chain with chosen AA setting:
    DXGI_RATIONAL RR;
    RR.Numerator = 60;
    RR.Denominator = 1;

    DXGI_SWAP_CHAIN_DESC SWDesc;
    ZeroMemory( &SWDesc, sizeof( SWDesc ) );
    SWDesc.BufferCount = 1;
    if (!config->FullScreenWindow)
    {
        SWDesc.BufferDesc.Width = config->cWidth;
        SWDesc.BufferDesc.Height = config->cHeight;
        SWDesc.BufferDesc.RefreshRate.Numerator = 60;
        SWDesc.BufferDesc.RefreshRate.Denominator = 1;
    }
    else
    {
        SWDesc.BufferDesc = config->Mode;
    }
    SWDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
    SWDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
    SWDesc.Flags = 0;
#ifdef _DEBUG
    //SWDesc.Flags |= D3D11_CREATE_DEVICE_DEBUG;
#endif
    SWDesc.OutputWindow = mGraphicsClient->mhWindow;
    SWDesc.SampleDesc = config->CurrentAAMode;


    SWDesc.Windowed = config->FullScreenWindow ? FALSE : TRUE;

    HR( Factory->CreateSwapChain( gd3dDevice, &SWDesc, &SwapChain ) );

//back buffer and depth/stencil buffer:
    HR( SwapChain->GetBuffer( 0, __uuidof(ID3D11Texture2D), (void**)&BackBuffer ) );

    D3D11_RENDER_TARGET_VIEW_DESC rtdesc;
    ZeroMemory( &rtdesc, sizeof(rtdesc) );
    rtdesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
    rtdesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DMS;
    rtdesc.Texture2D.MipSlice = 0;
    HR( gd3dDevice->CreateRenderTargetView( BackBuffer, &rtdesc, &BackBuffer_RTV ) );

    D3D11_TEXTURE2D_DESC DSDesc;
    ZeroMemory( &DSDesc, sizeof( D3D11_TEXTURE2D_DESC ) );
    DSDesc.Width = config->cWidth;
    DSDesc.Height = config->cHeight;
    DSDesc.MipLevels = 1;
    DSDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
    DSDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
    DSDesc.SampleDesc = config->CurrentAAMode;
    DSDesc.Usage = D3D11_USAGE_DEFAULT;
    DSDesc.CPUAccessFlags = 0;
    DSDesc.ArraySize = 1;
    DSDesc.MiscFlags = 0;

    ID3D11Texture2D *DepthStencil;
    HR( gd3dDevice->CreateTexture2D( &DSDesc, NULL, &DepthStencil ) );

    D3D11_DEPTH_STENCIL_VIEW_DESC DSVDesc;
    ZeroMemory( &DSVDesc, sizeof( DSVDesc ) );
    DSVDesc.Format = DSDesc.Format;
    DSVDesc.ViewDimension = config->CurrentAAMode.Count != 1 ? D3D11_DSV_DIMENSION_TEXTURE2DMS : D3D11_DSV_DIMENSION_TEXTURE2D;
    DSVDesc.Texture2D.MipSlice = 0;

    HR( gd3dDevice->CreateDepthStencilView( DepthStencil, &DSVDesc, &RTarget_DSV ) );

    REL( DepthStencil );

//set correct viewport
    D3D11_VIEWPORT VP;
    VP.Width = (float)config->cWidth;
    VP.Height = (float)config->cHeight;
    VP.MinDepth = 0.0f;
    VP.MaxDepth = 1.0f;
    VP.TopLeftX = 0;
    VP.TopLeftY = 0;

    iCtx->RSSetViewports( 1, &VP );

    //==========================
    //GDI-compatible buffer:
    //==========================
    D3D11_TEXTURE2D_DESC tdesc;
    ZeroMemory( &tdesc, sizeof(tdesc) );
    tdesc.Width = config->cWidth;
    tdesc.Height = config->cHeight;
    tdesc.MipLevels = 1;
    tdesc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;
    tdesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
    tdesc.SampleDesc.Count = 1;
    tdesc.SampleDesc.Quality = 0;
    tdesc.Usage = D3D11_USAGE_DEFAULT;
    tdesc.CPUAccessFlags = 0;
    tdesc.ArraySize = 1;
    tdesc.MiscFlags = D3D11_RESOURCE_MISC_GDI_COMPATIBLE;

    HR( gd3dDevice->CreateTexture2D( &tdesc, NULL, &PBuffer ) );

    //SRV:
    D3D11_SHADER_RESOURCE_VIEW_DESC sdesc;
    ZeroMemory( &sdesc, sizeof(sdesc));
    sdesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
    sdesc.Texture2D.MipLevels = 1;
    sdesc.Texture2D.MostDetailedMip = 0;
    sdesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
    HR( gd3dDevice->CreateShaderResourceView( PBuffer, &sdesc, &PBuffer_SRV ) );

    //RTV:
    ZeroMemory( &rtdesc, sizeof(rtdesc) );
    rtdesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
    rtdesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
    rtdesc.Texture2D.MipSlice = 0;

    HR( gd3dDevice->CreateRenderTargetView( PBuffer, &rtdesc, &PBuffer_RTV ) );

    //no additional buffers needed:
    RTarget_RTV = BackBuffer_RTV;
    RTarget_SRV = NULL;
    RTarget = BackBuffer;

    HR( PBuffer->QueryInterface( __uuidof(IDXGISurface1), reinterpret_cast<void**>(&PBuffer_Surf) ) );
//misc:
    InitGlobalVars();    //global constant buffers, states etc.

}

void Scene::InitStatics() {
    LabelFont = oapiCreateFont( 15, false, "Arial", FONT_NORMAL, 0 );
    DebugFont = oapiCreateFont( 15, true, "Consolas", FONT_NORMAL, 0 );
    NullPen = oapiCreatePen( 0, 1, 0xFFFFFF );
    DebugBrush = oapiCreateBrush( 0xB0000000 );

    LabelCol[0] = 0x00FFFF;
    LabelCol[1] = 0xFFFF00;
    LabelCol[2] = 0x4040FF;
    LabelCol[3] = 0xFF00FF;
    LabelCol[4] = 0x40FF40;
    LabelCol[5] = 0xFF8080;

    for( DWORD j = 0; j < 6; j++ )
        LabelPen[j] = oapiCreatePen( 1, 1, LabelCol[j] );

    pSketch = new D3D11Pad(mGraphicsClient->getConfig(),
                           this, NULL, GetTextureMgr(), true );

    D3D11Effect::InitGlobal( gd3dDevice, iCtx );
    mCelBkgrnd = new CelBackground(mGraphicsClient);

    near_plane = 1.0f;
    far_plane = 1e6;

    D3D11Pad::GlobalInit();
    D3D11Text::GlobalInit();

   
}

void Scene::InitGlobalVars() {
//constant buffers:
    D3D11_BUFFER_DESC desc;
    ZeroMemory( &desc, sizeof(desc) );
    desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
    desc.ByteWidth = 64;
    desc.CPUAccessFlags = 0;
    desc.MiscFlags = 0;
    desc.StructureByteStride = 0;
    desc.Usage = D3D11_USAGE_DEFAULT;

    HR( gd3dDevice->CreateBuffer( &desc, nullptr, &cb_D3DXMATRIX_x1 ) );

    ZeroMemory( &desc, sizeof(desc) );
    desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
    desc.ByteWidth = 128;
    desc.CPUAccessFlags = 0;
    desc.MiscFlags = 0;
    desc.StructureByteStride = 0;
    desc.Usage = D3D11_USAGE_DEFAULT;

    HR( gd3dDevice->CreateBuffer( &desc, nullptr, &cb_D3DXMATRIX_x2 ) );

    ZeroMemory( &desc, sizeof(desc) );
    desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
    desc.ByteWidth = 16;
    desc.CPUAccessFlags = 0;
    desc.MiscFlags = 0;
    desc.StructureByteStride = 0;
    desc.Usage = D3D11_USAGE_DEFAULT;

    HR( gd3dDevice->CreateBuffer( &desc, nullptr, &cb_D3DXVECTOR4 ) );

//blend states:
    D3D11_BLEND_DESC bdesc;
    ZeroMemory( &bdesc, sizeof(bdesc) );
    bdesc.AlphaToCoverageEnable = false;
    bdesc.IndependentBlendEnable = false;
    bdesc.RenderTarget[0].BlendEnable = false;
    bdesc.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA;
    bdesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE;
    bdesc.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA;
    bdesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO;
    bdesc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;
    bdesc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
    bdesc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;// D3D11_COLOR_WRITE_ENABLE_RED | D3D11_COLOR_WRITE_ENABLE_GREEN | D3D11_COLOR_WRITE_ENABLE_BLUE;
    HR( gd3dDevice->CreateBlendState( &bdesc, &BS_NoBlend ) );

    ZeroMemory( &bdesc, sizeof(bdesc) );
    bdesc.AlphaToCoverageEnable = false;
    bdesc.IndependentBlendEnable = false;
    bdesc.RenderTarget[0].BlendEnable = true;
    bdesc.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA;
    bdesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE;
    bdesc.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA;
    bdesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO;
    bdesc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;
    bdesc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
    bdesc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;//*/ D3D11_COLOR_WRITE_ENABLE_RED | D3D11_COLOR_WRITE_ENABLE_GREEN | D3D11_COLOR_WRITE_ENABLE_BLUE;//D3D11_COLOR_WRITE_ENABLE_ALL;
    HR( gd3dDevice->CreateBlendState( &bdesc, &BS_SrcAlpha ) );

    ZeroMemory( &bdesc, sizeof(bdesc) );
    bdesc.AlphaToCoverageEnable = false;
    bdesc.IndependentBlendEnable = false;
    bdesc.RenderTarget[0].BlendEnable = true;
    bdesc.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_COLOR;
    bdesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE;
    bdesc.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_COLOR;
    bdesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO;
    bdesc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;
    bdesc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
    bdesc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
    HR( gd3dDevice->CreateBlendState( &bdesc, &BS_InvSrcAlpha ) );

//rasterizer states:
	D3D11Config *config = mGraphicsClient->getConfig();
    D3D11_RASTERIZER_DESC rdesc;
    ZeroMemory( &rdesc, sizeof( rdesc ) );
    rdesc.CullMode = D3D11_CULL_BACK;
    rdesc.FillMode = D3D11_FILL_SOLID;
    rdesc.FrontCounterClockwise = FALSE;
    rdesc.MultisampleEnable = config->CurrentAAMode.Count != 1;
    HR( gd3dDevice->CreateRasterizerState( &rdesc, &RS_CullBack_Solid ) );

    ZeroMemory( &rdesc, sizeof( rdesc ) );
    rdesc.CullMode = D3D11_CULL_BACK;
    rdesc.FillMode = D3D11_FILL_WIREFRAME;
    rdesc.FrontCounterClockwise = FALSE;
    rdesc.MultisampleEnable = config->CurrentAAMode.Count != 1;
    HR( gd3dDevice->CreateRasterizerState( &rdesc, &RS_CullBack_Wire ) );

    ZeroMemory( &rdesc, sizeof( rdesc ) );
    rdesc.CullMode = D3D11_CULL_FRONT;
    rdesc.FillMode = D3D11_FILL_SOLID;
    rdesc.FrontCounterClockwise = FALSE;
    rdesc.MultisampleEnable = config->CurrentAAMode.Count != 1;
    HR( gd3dDevice->CreateRasterizerState( &rdesc, &RS_CullFront_Solid ) );

    ZeroMemory( &rdesc, sizeof( rdesc ) );
    rdesc.CullMode = D3D11_CULL_FRONT;
    rdesc.FillMode = D3D11_FILL_SOLID;
    rdesc.FrontCounterClockwise = FALSE;
    rdesc.MultisampleEnable = config->CurrentAAMode.Count != 1;
    HR( gd3dDevice->CreateRasterizerState( &rdesc, &RS_CullFront_Wire ) );

    ZeroMemory( &rdesc, sizeof( rdesc ) );
    rdesc.CullMode = D3D11_CULL_NONE;
    rdesc.FillMode = D3D11_FILL_SOLID;
    rdesc.FrontCounterClockwise = FALSE;
    rdesc.MultisampleEnable = config->CurrentAAMode.Count != 1;
    HR( gd3dDevice->CreateRasterizerState( &rdesc, &RS_CullNone_Solid ) );

    ZeroMemory( &rdesc, sizeof( rdesc ) );
    rdesc.CullMode = D3D11_CULL_NONE;
    rdesc.FillMode = D3D11_FILL_WIREFRAME;
    rdesc.FrontCounterClockwise = FALSE;
    rdesc.MultisampleEnable = config->CurrentAAMode.Count != 1;
    HR( gd3dDevice->CreateRasterizerState( &rdesc, &RS_CullNone_Wire ) );

//shader version:
    D3D_FEATURE_LEVEL feature = gd3dDevice->GetFeatureLevel();
    switch( feature ) {
    case D3D_FEATURE_LEVEL_9_1:
        strcpy( vs_ver, "vs_4_0_level_9_1" );
        strcpy( gs_ver, "gs_4_0_level_9_1" );
        strcpy( ps_ver, "ps_4_0_level_9_1" );
        break;
    case D3D_FEATURE_LEVEL_9_2:
        strcpy( vs_ver, "vs_4_0_level_9_1" );
        strcpy( gs_ver, "gs_4_0_level_9_1" );
        strcpy( ps_ver, "ps_4_0_level_9_1" );
        break;
    case D3D_FEATURE_LEVEL_9_3:
        strcpy( vs_ver, "vs_4_0_level_9_3" );
        strcpy( gs_ver, "gs_4_0_level_9_3" );
        strcpy( ps_ver, "ps_4_0_level_9_3" );
        break;
    case D3D_FEATURE_LEVEL_10_0:
        strcpy( vs_ver, "vs_4_0" );
        strcpy( gs_ver, "gs_4_0" );
        strcpy( ps_ver, "ps_4_0" );
        break;
    case D3D_FEATURE_LEVEL_10_1:
        strcpy( vs_ver, "vs_4_0" );
        strcpy( gs_ver, "gs_4_0" );
        strcpy( ps_ver, "ps_4_0" );
        break;
    case D3D_FEATURE_LEVEL_11_0:
        strcpy( vs_ver, "vs_5_0" );
        strcpy( gs_ver, "gs_5_0" );
        strcpy( ps_ver, "ps_5_0" );
        break;
    }

    ShaderCompileFlag =
        D3D10_SHADER_ENABLE_STRICTNESS | D3D10_SHADER_OPTIMIZATION_LEVEL3;

//sampler states:
    D3D11_SAMPLER_DESC sdesc;
    ZeroMemory( &sdesc, sizeof( sdesc ) );
    sdesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
    sdesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP;
    sdesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP;
    sdesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP;
    sdesc.ComparisonFunc = D3D11_COMPARISON_ALWAYS;
    sdesc.MaxAnisotropy = 4;
    sdesc.MipLODBias = 0;
    sdesc.MinLOD = 0;
    sdesc.MaxLOD = D3D11_FLOAT32_MAX;
    HR( gd3dDevice->CreateSamplerState( &sdesc, &SS_Linear_Wrap ) );

    ZeroMemory( &sdesc, sizeof( sdesc ) );
    sdesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
    sdesc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP;
    sdesc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP;
    sdesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP;
    sdesc.ComparisonFunc = D3D11_COMPARISON_ALWAYS;
    sdesc.MaxAnisotropy = 4;
    sdesc.MipLODBias = 0;
    sdesc.MinLOD = 0;
    sdesc.MaxLOD = D3D11_FLOAT32_MAX;
    HR( gd3dDevice->CreateSamplerState( &sdesc, &SS_Linear_Clamp ) );

    ZeroMemory( &sdesc, sizeof( sdesc ) );
    sdesc.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT ;
    sdesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP;
    sdesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP;
    sdesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP;
    sdesc.ComparisonFunc = D3D11_COMPARISON_ALWAYS;
    sdesc.MaxAnisotropy = 4;
    sdesc.MipLODBias = 0;
    sdesc.MinLOD = 0;
    sdesc.MaxLOD = D3D11_FLOAT32_MAX;
    HR( gd3dDevice->CreateSamplerState( &sdesc, &SS_Point_Wrap ) );

//texture for pixel/dot blits:
    D3D11_TEXTURE2D_DESC tdesc;
    ZeroMemory( &tdesc, sizeof(tdesc) );
    tdesc.ArraySize = 1;
    tdesc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;
    tdesc.CPUAccessFlags = 0;
    tdesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
    tdesc.Height = 2;
    tdesc.Width = 2;
    tdesc.MipLevels = 1;
    tdesc.MiscFlags = 0;
    tdesc.SampleDesc.Count = 1;
    tdesc.Usage = D3D11_USAGE_DEFAULT;

    HR( gd3dDevice->CreateTexture2D( &tdesc, NULL, &Tex_2x2 ) );

    D3D11_RENDER_TARGET_VIEW_DESC rtvdesc;
    ZeroMemory( &rtvdesc, sizeof( rtvdesc ) );
    rtvdesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
    rtvdesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
    rtvdesc.Texture2D.MipSlice = 0;

    HR( gd3dDevice->CreateRenderTargetView( Tex_2x2, &rtvdesc, &RTV_Tex_2x2 ) );

//depth-stencil states:
    D3D11_DEPTH_STENCIL_DESC dsdesc;
    ZeroMemory( &dsdesc, sizeof(dsdesc) );
    dsdesc.DepthEnable = false;
    dsdesc.DepthFunc = D3D11_COMPARISON_LESS_EQUAL;
    dsdesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ZERO;
    dsdesc.StencilEnable = false;

    HR( gd3dDevice->CreateDepthStencilState( &dsdesc, &DSS_NoDepth_NoStencil ) );

    ZeroMemory( &dsdesc, sizeof(dsdesc) );
    dsdesc.DepthEnable = true;
    dsdesc.DepthFunc = D3D11_COMPARISON_LESS_EQUAL;
    dsdesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ZERO;
    dsdesc.StencilEnable = false;

    HR( gd3dDevice->CreateDepthStencilState( &dsdesc, &DSS_TestDepthOnly_NoStencil ) );
}

void Scene::DeleteGlobalVars() {
    REL( SS_Point_Wrap );
    REL( SS_Linear_Wrap );
    REL( SS_Linear_Clamp );

    REL( cb_D3DXMATRIX_x1 );
    REL( cb_D3DXMATRIX_x2 );
    REL( cb_D3DXVECTOR4 );

    REL( RS_CullBack_Solid );
    REL( RS_CullBack_Wire );
    REL( RS_CullFront_Solid );
    REL( RS_CullFront_Wire );
    REL( RS_CullNone_Solid );
    REL( RS_CullNone_Wire );

    REL( BS_SrcAlpha );
    REL( BS_InvSrcAlpha );
    REL( BS_NoBlend );

    REL( DSS_NoDepth_NoStencil );
    REL( DSS_TestDepthOnly_NoStencil );

    REL( Tex_2x2 );
    REL( RTV_Tex_2x2 );

    REL( SwapChain );
}

//=================================================
//            Object creation.
//=================================================

void Scene::InitObjects() {
    DWORD j, starcount = 0, i = 0;
    OBJHANDLE obj;

    D3DXMatrixIdentity( &ViewProj );
    CamPos.x = CamPos.y = CamPos.z = 0.0;
    //all bases should be created in their planets.
}

#pragma endregion

float  Scene::GetLuminance()
{
    return  0.2f;
}

void Scene::Exit3D() {
    BOOL isFullscreen = FALSE;
    SwapChain->GetFullscreenState(&isFullscreen, nullptr);
    if (isFullscreen)
    {
        SwapChain->SetFullscreenState(FALSE, nullptr);
    }
  
    TileManager::GlobalExit();
    D3D11Pad::GlobalExit();
    D3D11Text::GlobalExit();
   

    D3D11Effect::ExitGlobal();
   
    CelBackground::ExitCelBackgroundEffect();
   
    
}
